home *** CD-ROM | disk | FTP | other *** search
- /* f w r i t e
- *
- * This function writes a series of records to the output stream.
- * The function returns the number of items written to the stream.
- * Writing stops when the correct number of items have been written
- * or when the function encounters an error.
- *
- * Patchlevel 1.1
- *
- * Edit History:
- * 05-Sep-1989 Include limits.h if INT_MAX undefined so removing
- * need to define MINIX when compiling. Assign void *
- * to unsigned char * to avoid casting problems.
- * 04-Sep-1989 Add code to deal with really large objects.
- * 03-Sep-1989 Write to buffer only if it requires at most one call
- * to write(), otherwise use write() directly.
- * 01-Sep-1989 Use Collyer's idea to speed up by doing writes directly
- * from buffer.
- */
-
- #include "stdiolib.h"
-
- #if defined(BSD)
- # include <values.h>
- # define INT_MAX (MAXINT)
- #endif
-
- #if !defined(INT_MAX)
- # include <limits.h>
- #endif
-
- /*LINTLIBRARY*/
-
- int fwrite(ptr, size, nitems, fp)
-
- CONST void *ptr; /* buffer */
- unsigned int size; /* size of item */
- unsigned int nitems; /* number of items */
- FILE *fp; /* stream */
-
- {
- int wrote; /* bytes written in write call */
- int write(); /* write call */
- unsigned char *p; /* buffer pointer */
-
- /* Phase 1 --- Amount to write overflows INT_MAX */
- unsigned int burstsize; /* size aligned chunk to write */
- unsigned int itemsperburst; /* items written per burst */
- unsigned int itemsleft; /* items left */
-
- /* Phase 2 --- Write remainder */
- unsigned int bytestotal; /* total number of bytes */
- unsigned int bytesleft; /* total number of bytes left */
- unsigned int copybytes; /* bytes to copy */
- unsigned char *q; /* pointer into putc buffer */
-
- /* Items left to write */
- if ((itemsleft = nitems) == 0 || size == 0)
- return 0;
-
- /* Fix void * casting problems */
- p = (unsigned char *) ptr;
-
- /* Very large objects */
- if ((itemsperburst = INT_MAX / size) == 0) {
- (void) fflush(fp);
- do {
- bytesleft = size;
- do {
- if ((burstsize = INT_MAX) > bytesleft)
- burstsize = bytesleft;
- if ((wrote = write(fileno(fp), (char *) p, (int) burstsize)) !=
- burstsize)
- return (nitems-itemsleft);
- p += burstsize;
- } while ((bytesleft -= burstsize) != 0);
- } while (--itemsleft);
- return nitems;
- }
-
- /* Write large amounts of data for small objects */
- for (burstsize = itemsperburst * size; itemsleft > itemsperburst; ) {
- if (itemsleft == nitems)
- (void) fflush(fp);
- if ((wrote = write(fileno(fp), (char *) p, (int) burstsize)) != burstsize) {
- if (wrote == -1)
- wrote = 0;
- return (nitems-itemsleft) + (wrote/size);
- }
- p += burstsize;
- itemsleft -= itemsperburst;
- }
-
- /* At this point itemsleft contains the number of items left to
- * write. The output buffer may not be empty. itemsleft*size
- * will not overflow INT_MAX.
- */
-
- if ((bytesleft = bytestotal = size*itemsleft) != 0) {
-
- /* Unallocated buffer */
- if (! HASBUFFER(fp)) {
- if (_allocbuf(fp) < 0)
- return (nitems-itemsleft);
- SETIOFLUSH();
- }
-
- /* Partially filled write buffer */
- if (! TESTFLAG(fp, _IONBF) &&
- bytesleft <= UNUSEDINWRITEBUFFER(fp) + BUFFERSIZE(fp)) {
- do {
- if ((copybytes = UNUSEDINWRITEBUFFER(fp)) > bytesleft)
- copybytes = bytesleft;
- wrote = copybytes;
- q = GETWRITEPTR(fp);
- UNROLL_DO(fwritebytes, copybytes, *q++ = *p++);
- SETWRITEPTR(fp, q);
- if (bytesleft > wrote && fflush(fp) == EOF)
- break;
- } while ((bytesleft -= wrote) != 0);
-
- if (TESTFLAG(fp, _IOLBF) && bytesleft == 0)
- (void) fflush(fp);
- }
-
- /* Dump rest of object directly to file */
- else if (fflush(fp) != EOF &&
- (wrote = write(fileno(fp), (char *) p, (int) bytesleft)) != -1)
- bytesleft -= wrote;
- }
-
- return (nitems-itemsleft) + (bytestotal-bytesleft)/size;
- }
-